﻿using FDFtpSync.Core;
using FDFtpSync.Entities;
using FDFtpSync.Entities.Extensions;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;

namespace FDFtpSync.Client
{
    public abstract class BaseSyncServer : IFileSyncServer
    {
        protected bool _stop, _isRunning;
        protected DateTime _lastRunTime;
        private ILogger _logger;

        public BaseSyncServer(ILogger logger)
        {
            _logger = logger;
        }

        public void Start()
        {
            var clientConfig = SyncContext.Current.GetSyncConfig<ClientSyncConfig>();
            //ThreadPool.SetMaxThreads(clientConfig.Threads, clientConfig.Threads);
            _stop = false;

            _lastRunTime = DateTime.Now.AddSeconds(-clientConfig.IntervalSeconds);
            while (!_stop)
            {
                if (NeedRun())
                {
                    Run();
                }
            }
        }

        protected abstract void Run();

        public void Stop()
        {
            _stop = true;
        }

        protected bool NeedRun()
        {
            var now = DateTime.Now;
            return (now - _lastRunTime).TotalSeconds > SyncContext.Current.GetSyncConfig<ClientSyncConfig>().IntervalSeconds;
        }

        protected void WriteToFile(string saveFileName, Stream stream, bool bAppend = false)
        {
            using (var fs = new FileStream(saveFileName, FileMode.Append, FileAccess.Write))
            {
                if (bAppend)
                {
                    fs.Seek(fs.Length, SeekOrigin.Begin);
                }

                var buffer = new byte[1024 * 1024 * 1024];
                int count;
                while ((count = stream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    fs.Write(buffer, 0, count);
                }
            }
        }

        protected string GetFileMd5(string path, string pathName)
        {
            using (var client = new HttpClient())
            {
                var content = new StringContent(new { FileName = path, PathName = pathName }.ToJson());
                content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                var res = client.PostAsync(SyncContext.Current.GetSyncConfig<ClientSyncConfig>().FileMd5Url, content).Result.Content.ReadAsStringAsync().Result;
                var apiRes = res.FromJson<ApiResult<string>>();
                if (apiRes.Code == 0)
                {
                    return apiRes.Result;
                }

                return string.Empty;
            }
        }

        protected void TryDo(Action action)
        {
            try
            {
                action?.Invoke();
            }
            catch (Exception ex)
            {
                _logger.Error("", ex);
            }
        }

        protected void Info(string msg)
        {
            _logger.Info(msg);
        }
    }
}
